<script lang="ts" setup>
// 引入 bpmn 相关接口
import { getProcessDefinitionXml, saveProcessDefinitionXml } from '@/api/process/processDefinitionApi'
// 引入pinia
import piniaStore from '@/store'
// 引入BPMN小仓库
import useBPMNStore from '@/store/bpmn/bpmnStore'
/**
 * 引入 自定义翻译函数，用于处理 BPMN XML 中的占位符替换。
 */
import customTranslate from '@/utils/flowable/customTranslater'
/**
 * 引入默认 xml
 */
import { xmlStr } from '@/views/process/files/xmlStr'

/**
 * 从 bpmn-js-properties-panel 包中引入模块，用于支持属性面板功能。
 */
import {
  BpmnPropertiesPanelModule,
  BpmnPropertiesProviderModule,
  CamundaPlatformPropertiesProviderModule,
} from 'bpmn-js-properties-panel'

/**
 * 引入 BpmnModeler 类，用于创建和操作 BPMN 图表。
 */
import BpmnModeler from 'bpmn-js/lib/Modeler'

/**
 * 引入 Camunda Moddle 描述符，用于扩展 BPMN 模型以支持 Camunda 特性。
 */
import CamundaBpmnModdle from 'camunda-bpmn-moddle/resources/camunda.json'

// 引入 Element Plus 的消息提示组件
import { ElMessage } from 'element-plus'

/**
 * 从 Vue 中引入生命周期钩子和响应式引用。
 */
import { onMounted, ref } from 'vue'

// 使用BPMN小仓库
const bpmnStore = useBPMNStore(piniaStore)

/**
 * 定义 canvasRef，用于引用 BPMN 图表的容器 DOM 元素。
 */
const canvasRef = ref<HTMLDivElement | null>(null)

/**
 * 定义 propertiesPanelRef，用于引用属性面板的容器 DOM 元素。
 */
const propertiesPanelRef = ref<HTMLDivElement | null>(null)

/**
 * 定义 modeler 变量，用于存储 BpmnModeler 实例。
 */
let modeler: BpmnModeler | null = null

// 当组件挂载时，异步初始化BPMN建模器
onMounted(async () => {
  await initializeBpmnModeler()
})

/**
 * 异步函数：初始化 BPMN 模型器
 *
 * 该函数负责初始化 BPMN 模型器实例，并根据提供的 processKey 加载相应的 BPMN XML 文件
 * 如果指定的 XML 文件不存在，则加载一个默认的 XML 文件
 */
async function initializeBpmnModeler() {
  // 检查 canvas 和 properties panel 的引用是否存在
  if (canvasRef.value && propertiesPanelRef.value) {
    // 翻译转换器
    const translateModule = {
      translate: ['value', customTranslate],
    }

    // 初始化 BpmnModeler 实例，配置容器、属性面板和扩展模块
    modeler = new BpmnModeler({
      container: canvasRef.value,
      propertiesPanel: {
        parent: propertiesPanelRef.value,
      },
      additionalModules: [
        BpmnPropertiesPanelModule,
        BpmnPropertiesProviderModule,
        CamundaPlatformPropertiesProviderModule,
        // 自定义翻译转换器
        translateModule,
      ],
      moddleExtensions: {
        camunda: CamundaBpmnModdle,
      },
    })

    // 根据 pinia 中的 processKey 查询BPMN XML
    const xmlStr1 = await getXml(bpmnStore.processKey)
    if (xmlStr1) {
      // 导入 BPMN XML 字符串并处理成功后的逻辑
      await modeler.importXML(xmlStr1).then(() => {
        // 成功后操作（此处可添加具体逻辑）。
      })
    }
    else {
      // 导入默认字符串并处理成功后的逻辑
      await modeler.importXML(xmlStr).then(() => {
        // 成功后操作（此处可添加具体逻辑）。
      })
    }
  }
}

/**
 * 根据流程键获取XML定义
 *
 * 此函数调用`getProcessDefinitionXml`来获取流程定义的XML
 * 如果调用成功且返回代码为200，则返回XML数据，否则返回空字符串
 *
 * @param processKey 可选参数，用于指定流程的唯一键
 * @returns 成功时返回流程定义的XML，否则返回空字符串
 */
async function getXml(processKey?: string) {
  // 获取xml
  const result: any = await getProcessDefinitionXml({
    processKey,
  })

  if (result.success && result.code === 200) {
    return result.data
  }
  else {
    return ''
  }
}

/**
 * 异步保存函数
 * 该函数负责将模型编辑器中的XML数据保存到服务器
 */
async function onSave() {
  // 定义 processXmlParam，允许为 string 或 undefined
  let processXmlParam: string | undefined

  try {
    // 保存逻辑：获取格式化后的XML字符串
    const { xml } = await modeler?.saveXML({ format: true }) || {}
    if (xml !== undefined) {
      processXmlParam = xml // 如果xml存在，则赋值
    }
    else {
      processXmlParam = '' // 如果xml不存在，设置为空字符串
    }

    // 调用接口保存XML
    const result: any = await saveProcessDefinitionXml({
      processKey: bpmnStore.processKey,
      processXml: processXmlParam || '', // 确保传递的参数为字符串
    })

    // 根据保存结果执行相应的操作
    if (result.success && result.code === 200) {
      ElMessage({
        message: '保存成功',
        type: 'success',
      })
    }
    else {
      ElMessage({
        message: '保存失败',
        type: 'error',
      })
    }
  }
  catch (error) {
    // 处理异常
    let errorMessage = '未知错误'
    if (error instanceof Error) {
      errorMessage = error.message
    }
    // 显示错误消息
    ElMessage({
      message: `保存失败: ${errorMessage || '未知错误'}`,
      type: 'error',
    })
  }
}
</script>

<template>
  <el-card style="height: 75px;">
    <el-button type="primary" @click="onSave">
      保存
    </el-button>
  </el-card>

  <!-- bpmn区域 -->
  <el-card style="margin: 10px 0px;">
    <div class="bpmn-container bpmn-color">
      <!-- BPMN 图表的主画布区域 -->
      <div ref="canvasRef" class="canvas" />
      <!-- 属性面板区域 -->
      <div ref="propertiesPanelRef" class="properties-panel" />
    </div>
  </el-card>
</template>

<style scoped>
.bpmn-container {
  display: flex;
  height: 700px;
}

.canvas {
  flex: 3; /* 占据 3/4 的宽度 */
  border: 1px solid #ccc; /* 添加边框以便区分区域 */
}

.properties-panel {
  flex: 1; /* 占据 1/4 的宽度 */
  border-left: 1px solid #ccc; /* 左侧边框分隔画布和属性面板 */
  overflow-y: auto; /* 支持垂直滚动 */
}
</style>
